home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xpaint-2.1.1
/
graphic.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
41KB
|
1,655 lines
/* +-------------------------------------------------------------------+ */
/* | Copyright 1992, 1993, David Koblas (koblas@netcom.com) | */
/* | | */
/* | Permission to use, copy, modify, and to distribute this software | */
/* | and its documentation for any purpose is hereby granted without | */
/* | fee, provided that the above copyright notice appear in all | */
/* | copies and that both that copyright notice and this permission | */
/* | notice appear in supporting documentation. There is no | */
/* | representations about the suitability of this software for | */
/* | any purpose. this software is provided "as is" without express | */
/* | or implied warranty. | */
/* | | */
/* +-------------------------------------------------------------------+ */
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Toggle.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/Paned.h>
#ifdef HAVE_COLTOG
#include "ColToggle.h"
#endif
#include <stdio.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef NOSTDHDRS
#include <stdlib.h>
#include <unistd.h>
#endif
#define LOOKUP_OUTSIDE
#include "Paint.h"
#include "xpaint.h"
#include "palette.h"
#include "misc.h"
#include "menu.h"
#include "text.h"
#include "image.h"
#include "cutCopyPaste.h"
#include "rc.h"
#define DEFAULT_TITLE "Untitled"
#define PATTERN(name) \
(char *)CONCAT(name,_bits), CONCAT(name,_width), CONCAT(name,_height)
struct paintWindows {
Widget paint;
struct paintWindows *next;
void *ldata;
Boolean done;
};
typedef struct {
Widget paint;
Palette *map;
Widget primaryBox, secondaryBox;
Widget primaryList, secondaryList;
Widget first, second;
} LocalInfo;
/*
** Forward references
*/
static void makePaletteArea(LocalInfo*, RCInfo*);
static void editPatternCB(Widget, Widget);
static void deletePatternCB(Widget, Widget);
/*
** Begin menus
*/
static PaintMenuItem fileMenu[] = {
#define SAVE_ITEM 0
MI_SIMPLE("save"),
#define SAVEAS_ITEM 1
MI_SIMPLE("saveas"),
#define SAVER_ITEM 2
MI_SIMPLE("saveregion"),
#define SAVE_CONFIG 3
MI_SIMPLE("saveconfig"),
#define LOAD_CONFIG 4
MI_SIMPLE("loadconfig"),
#define CLOSE_ITEM 5
MI_SIMPLE("close"),
};
static PaintMenuItem editMenu[] = {
#define UNDO_ITEM 0
MI_SIMPLE("undo"),
MI_SEPERATOR(),
#define CUT_ITEM 2
MI_SIMPLE("cut"),
#define COPY_ITEM 3
MI_SIMPLE("copy"),
#define PASTE_ITEM 4
MI_SIMPLE("paste"),
#define CLEAR_ITEM 5
MI_SIMPLE("clear"),
MI_SEPERATOR(),
#define DUP_ITEM 7
MI_SIMPLE("dup"),
#define SELECT_ALL_ITEM 8
MI_SIMPLE("all"),
#if 0
{ "lock", NULL, NULL, MF_NONE, 0, NULL },
{ "unlock", NULL, NULL, MF_NONE, 0, NULL },
#endif
};
static PaintMenuItem rotateMenu[] = {
MI_SEPERATOR(),
MI_SIMPLE("rotate1"),
MI_SIMPLE("rotate2"),
MI_SIMPLE("rotate3"),
MI_SIMPLE("rotate4"),
MI_SIMPLE("rotate5"),
};
static PaintMenuItem regionMenu[] = {
#define RG_FLIPX_ITEM 0
MI_SIMPLE("flipX"),
#define RG_FLIPY_ITEM 1
MI_SIMPLE("flipY"),
MI_SEPERATOR(),
#define RG_ROTATETO 3
MI_RIGHT("rotateTo", XtNumber(rotateMenu), rotateMenu),
#define RG_ROTATE 4
MI_SIMPLE("rotate"),
MI_SEPERATOR(),
#define RG_INVERT_ITEM 6
MI_SIMPLE("invert"),
#define RG_SHARPEN_ITEM 7
MI_SIMPLE("sharpen"),
#define RG_SMOOTH_ITEM 8
MI_SIMPLE("smooth"),
#define RG_EDGE_ITEM 9
MI_SIMPLE("edge"),
#define RG_EMBOSE_ITEM 10
MI_SIMPLE("emboss"),
#define RG_OIL_ITEM 11
MI_SIMPLE("oil"),
MI_SEPERATOR(),
#if 0
#define RG_BOX 13
MI_SIMPLE("nudge"),
MI_SEPERATOR(),
#define RG_RESET 15
#endif
#define RG_RESET 13
MI_SIMPLE("reset"),
};
static PaintMenuItem otherMenu[] = {
#define FAT_ITEM 0
MI_SIMPLE("fatbits"),
#define GRID_ITEM 1
MI_FLAG("grid", MF_CHECK),
#define SNAP_ITEM 2
MI_FLAG("snap", MF_CHECK),
#define CHSNAP_ITEM 3
MI_SIMPLE("snapSpacing"),
MI_SEPERATOR(),
#define EDIT_BACKGROUND 5
MI_SIMPLE("background"),
MI_SEPERATOR(),
#define CHSIZE_ITEM 7
MI_SIMPLE("size"),
#define CHZOOM_ITEM 8
MI_SIMPLE("zoom"),
};
static PaintMenuItem helpMenu[] = {
MI_SIMPLECB("help", HelpDialog, "canvas"),
};
static PaintMenuBar menuBar[] = {
{ None, "file", XtNumber(fileMenu), fileMenu },
{ None, "edit", XtNumber(editMenu), editMenu },
{ None, "region", XtNumber(regionMenu), regionMenu },
{ None, "other", XtNumber(otherMenu), otherMenu },
{ None, "help", XtNumber(helpMenu), helpMenu },
};
static PaintMenuItem paletteMenu[] = {
MI_SEPERATOR(),
MI_SIMPLECB("edit", (PaintMenuCallback)editPatternCB, NULL),
MI_SIMPLECB("remove", (PaintMenuCallback)deletePatternCB, NULL),
MI_SEPERATOR(),
MI_SIMPLECB("help", HelpDialog, "canvas.patBox"),
};
/*
** End of menus
*/
static struct paintWindows *head = NULL;
void GraphicRemove(Widget paint, XtPointer junk, XtPointer junk2)
{
struct paintWindows *cur = head, **prev = &head;
while (cur != NULL && cur->paint != paint) {
prev = &cur->next;
cur = cur->next;
}
if (cur == NULL)
return;
*prev = cur->next;
if (cur->done)
CurrentOp[1](cur->paint, cur->ldata);
XtFree((XtPointer)cur);
}
static void destroyCallback(Widget paint, XtPointer data, XtPointer junk2)
{
LocalInfo *info = (LocalInfo *)data;
Colormap cmap;
Palette *map;
XtVaGetValues(paint, XtNcolormap, &cmap, NULL);
if ((map = PaletteFind(paint, cmap)) != NULL)
PaletteDelete(map);
XtFree((XtPointer)info);
}
static void realize(Widget paint, XtPointer ldataArg, XEvent *event, Boolean *junk)
{
struct paintWindows *cur = (struct paintWindows*)ldataArg;
if (event->type == MapNotify) {
XtRemoveEventHandler(paint, StructureNotifyMask, False, realize, ldataArg);
if (CurrentOp != NULL && CurrentOp[0] != NULL)
cur->ldata = CurrentOp[0](paint);
cur->done = True;
}
}
void GraphicAdd(Widget paint)
{
struct paintWindows *new = XtNew(struct paintWindows);
new->next = head;
head = new;
new->paint = paint;
new->ldata = NULL;
new->done = False;
if (XtIsRealized(paint)) {
if (CurrentOp != NULL && CurrentOp[0] != NULL)
new->ldata = CurrentOp[0](paint);
new->done = True;
} else {
XtAddEventHandler(paint, StructureNotifyMask, False, realize, (XtPointer)new);
}
XtAddCallback(paint, XtNdestroyCallback, GraphicRemove, NULL);
}
void GraphicAll(void (*func)(), void *data)
{
struct paintWindows *cur;
for (cur = head; cur != NULL; cur=cur->next) {
if (!cur->done)
continue;
func(cur->paint, data);
}
}
void GraphicSetOp(void (*stop)(Widget, void *), void *(*start)(Widget))
{
struct paintWindows *cur;
for (cur = head; cur != NULL; cur=cur->next) {
if (stop != NULL)
stop(cur->paint, cur->ldata);
if (start != NULL)
cur->ldata = start(cur->paint);
}
}
void *GraphicGetData(Widget w)
{
struct paintWindows *cur;
for (cur = head; cur != NULL; cur=cur->next)
if (cur->paint == w)
return cur->ldata;
return NULL;
}
/*
** Pattern creation and chaning, utilitys.
*/
#define PAT_MIN_WH 24
typedef struct {
Widget paint;
Widget widget, widget2;
int width, height;
Pixmap pixmap, shownPixmap;
Pixel pixel;
LocalInfo *li;
} PatternInfo;
static void patternUpdate(PatternInfo *info, Boolean isFirst)
{
char *w_fr, *w_fg, *w_pat;
if (isFirst) {
w_fr = XtNfillRule;
w_fg = XtNforeground;
w_pat = XtNpattern;
} else {
w_fr = XtNlineFillRule;
w_fg = XtNlineForeground;
w_pat = XtNlinePattern;
}
if (info->pixmap == None) {
XtVaSetValues(info->paint, w_fg, info->pixel,
w_fr, FillSolid,
NULL);
} else {
XtVaSetValues(info->paint, w_pat, info->pixmap,
w_fr, FillTiled,
NULL);
}
}
static void setPatternCallback(Widget icon, PatternInfo *info, XtPointer junk2)
{
Widget rg;
Boolean state;
XtVaGetValues(icon, XtNstate, &state, XtNradioGroup, &rg, NULL);
if (state == False)
return;
if (rg == info->li->primaryList || info->li->primaryList == icon)
patternUpdate(info, True);
else
patternUpdate(info, False);
}
static void freePatternInfo(Widget icon, PatternInfo *info)
{
if (info->pixmap != info->shownPixmap)
XFreePixmap(XtDisplay(icon), info->shownPixmap);
if (info->pixmap != None)
XFreePixmap(XtDisplay(icon), info->pixmap);
XtFree((XtPointer)info);
}
static void installPatternPixmap(PatternInfo *info, Pixmap pix)
{
XtPointer curPrimary, curSecondary;
curPrimary = XawToggleGetCurrent(info->li->primaryList);
curSecondary = XawToggleGetCurrent(info->li->secondaryList);
if (curPrimary == (XtPointer)info)
XawToggleUnsetCurrent(info->li->primaryList);
if (curSecondary == (XtPointer)info)
XawToggleUnsetCurrent(info->li->secondaryList);
XtVaSetValues(info->widget, XtNbitmap, pix, NULL);
XtVaSetValues(info->widget2, XtNbitmap, pix, NULL);
if (curPrimary == (XtPointer)info)
XawToggleSetCurrent(info->li->primaryList, curPrimary);
if (curSecondary == (XtPointer)info)
XawToggleSetCurrent(info->li->secondaryList, curSecondary);
}
static void editSolidOk(Widget paint, PatternInfo *info, XColor *col)
{
LocalInfo *l = info->li;
StateShellBusy(paint, False);
if (col == NULL)
return;
if (!PaletteSetPixel(l->map, info->pixel, col)) {
/*
** This will fail for because we are on a static screen
** if it is a TrueColor screen change the "icon"
*/
if (!l->map->isMapped) {
/*
** TrueColor
*/
Pixel p = PaletteAlloc(l->map, col);
Display *dpy = XtDisplay(paint);
GC gc = XCreateGC(dpy, XtWindow(paint), 0, 0);
Pixmap pix;
int depth;
XtVaGetValues(info->widget, XtNdepth, &depth, NULL);
pix = XCreatePixmap(dpy, DefaultRootWindow(dpy), PAT_MIN_WH, PAT_MIN_WH, depth);
XSetForeground(dpy, gc, p);
XFillRectangle(dpy, pix, gc, 0, 0, PAT_MIN_WH, PAT_MIN_WH);
info->pixel = p;
installPatternPixmap(info, pix);
XFreePixmap(dpy, info->shownPixmap);
info->shownPixmap = pix;
XFreeGC(dpy, gc);
}
}
}
static void editPatternAction(Widget w, XEvent *event)
{
PatternInfo *info;
XtVaGetValues(w, XtNradioData, &info, NULL);
if (info->pixmap == None) {
LocalInfo *l = (LocalInfo *)info->li;
if (!l->map->readonly || !l->map->isMapped) {
StateShellBusy(l->paint, True);
ColorEditor(l->paint, info->pixel, l->map, True,
(XtCallbackProc)editSolidOk, (XtPointer)info);
}
} else {
void PatternEdit(Widget, Pixmap, Widget);
PatternEdit(info->paint, info->pixmap, w);
}
}
static void deletePatternCB(Widget mb, Widget w)
{
LocalInfo *li;
PatternInfo *info, *ainfo;
Widget parent;
WidgetList children;
int nchild;
Boolean setFirst = False;
Boolean actPrimary = False, actSecondary = False;
XtVaGetValues(w, XtNradioData, &info, NULL);
/*
** Check to see if it is active
*/
ainfo = (PatternInfo*)XawToggleGetCurrent(info->widget);
if (info == ainfo) {
XawToggleUnsetCurrent(info->widget);
actPrimary = True;
}
ainfo = (PatternInfo*)XawToggleGetCurrent(info->widget2);
if (info == ainfo) {
XawToggleUnsetCurrent(info->widget2);
actSecondary = True;
}
/*
** Make sure there is enough widgets
*/
XtVaGetValues(parent = XtParent(info->widget),
XtNnumChildren, &nchild,
XtNchildren, &children,
NULL);
if (nchild == 1) {
Notice(w, "You must have at least one entry");
return;
}
li = info->li;
if (info->widget == li->primaryList)
setFirst = True;
XtDestroyWidget(info->widget);
XtDestroyWidget(info->widget2);
if (setFirst) {
XtVaGetValues(parent, XtNchildren, &children, NULL);
if (children[0] == info->widget)
li->primaryList = children[1];
else
li->primaryList = children[0];
XtVaGetValues(li->primaryList, XtNradioData, &info, NULL);
li->secondaryList = info->widget2;
}
if (actPrimary) {
XtVaGetValues(li->primaryList, XtNradioData, &info, NULL);
XawToggleSetCurrent(li->primaryList, (XtPointer)info);
}
if (actSecondary) {
XtVaGetValues(li->secondaryList, XtNradioData, &info, NULL);
XawToggleSetCurrent(li->secondaryList, (XtPointer)info);
}
}
static void editPatternCB(Widget mb, Widget w)
{
editPatternAction(w, NULL);
}
/*
** Special trick so that during creationg of the pattern box
** initialization can happen
*/
static LocalInfo *hiddenLocalInfo;
Widget AddPattern(Widget group, Widget paint, Pixmap pix, Pixel pxl)
{
static XtTranslations trans = None;
static GC gc = None;
static Boolean added = False;
Widget parent, iconA, iconB, box;
PatternInfo *info = XtNew(PatternInfo);
Display *dpy = XtDisplay(group);
int depth;
char *nm = "pattern";
if (!added) {
static XtActionsRec v = { "editPattern", (XtActionProc)editPatternAction };
XtAppAddActions(XtWidgetToApplicationContext(paint), &v, 1);
added = True;
}
if (trans == None)
trans = XtParseTranslationTable("<BtnDown>,<BtnUp>: set() notify()\n<BtnDown>(2): editPattern()");
if (XtClass(group) == toggleWidgetClass) {
PatternInfo *tpi;
parent = XtParent(group);
XtVaGetValues(group, XtNradioData, &tpi, NULL);
info->li = tpi->li;
#ifdef HAVE_COLTOG
} else if (XtClass(group) == colToggleWidgetClass) {
PatternInfo *tpi;
parent = XtParent(group);
XtVaGetValues(group, XtNradioData, &tpi, NULL);
info->li = tpi->li;
#endif
} else {
parent = group;
group = None;
info->li = hiddenLocalInfo;
}
box = parent;
info->paint = paint;
if (pix != None) {
GetPixmapWHD(dpy, pix, &info->width, &info->height, &depth);
info->pixmap = pix;
if (info->width == 1 && info->height == 1) {
XImage *xim = XGetImage(XtDisplay(paint), pix, 0, 0, 1, 1, AllPlanes, ZPixmap);
info->pixel = XGetPixel(xim, 0, 0);
XDestroyImage(xim);
info->pixmap = None;
pix = None;
}
} else {
info->pixel = pxl;
info->pixmap = None;
XtVaGetValues(parent, XtNdepth, &depth, NULL);
}
if (info->pixmap == None)
nm = "solid";
if (info->pixmap == None) {
/* XXX Getting a read only GC, and writing to it */
if (gc == None) gc = XtGetGC(paint, 0, 0);
pix = XCreatePixmap(dpy, DefaultRootWindow(dpy), PAT_MIN_WH, PAT_MIN_WH, depth);
XSetForeground(dpy, gc, info->pixel);
XFillRectangle(dpy, pix, gc, 0, 0, PAT_MIN_WH, PAT_MIN_WH);
} else if (info->width < PAT_MIN_WH || info->height < PAT_MIN_WH) {
int nw = (info->width < PAT_MIN_WH) ? PAT_MIN_WH : info->width;
int nh = (info->height < PAT_MIN_WH) ? PAT_MIN_WH : info->height;
int x, y;
if (gc == None) gc = XtGetGC(paint, 0, 0);
pix = XCreatePixmap(dpy, DefaultRootWindow(dpy), nw, nh, depth);
for (y = 0; y < nh; y += info->height)
for (x = 0; x < nw; x += info->width)
XCopyArea(dpy, info->pixmap, pix, gc,
0, 0, info->width, info->height, x, y);
}
#ifdef HAVE_COLTOG
if (info->pixmap == None) {
iconA = XtVaCreateManagedWidget(nm, colToggleWidgetClass,
info->li->primaryBox,
XtNforeground, info->pixel,
XtNradioGroup, info->li->primaryList,
XtNtranslations, trans,
XtNradioData, info,
XtNisSolid, True,
NULL);
iconB = XtVaCreateManagedWidget(nm, colToggleWidgetClass,
info->li->secondaryBox,
XtNforeground, info->pixel,
XtNradioGroup, info->li->secondaryList,
XtNtranslations, trans,
XtNradioData, info,
XtNisSolid, True,
NULL);
} else {
#endif
iconA = XtVaCreateManagedWidget(nm, toggleWidgetClass,
info->li->primaryBox,
XtNbitmap, pix,
XtNradioGroup, info->li->primaryList,
XtNtranslations, trans,
XtNradioData, info,
NULL);
iconB = XtVaCreateManagedWidget(nm, toggleWidgetClass,
info->li->secondaryBox,
XtNbitmap, pix,
XtNradioGroup, info->li->secondaryList,
XtNtranslations, trans,
XtNradioData, info,
NULL);
#ifdef HAVE_COLTOG
}
#endif
if (info->li->primaryList == None)
info->li->primaryList = iconA;
if (info->li->secondaryList == None)
info->li->secondaryList = iconB;
XtAddCallback(iconA, XtNcallback, (XtCallbackProc)setPatternCallback, (XtPointer)info);
XtAddCallback(iconB, XtNcallback, (XtCallbackProc)setPatternCallback, (XtPointer)info);
paletteMenu[1].data = (void*)iconA;
paletteMenu[2].data = (void*)iconA;
MenuPopupCreate(iconA, XtNumber(paletteMenu), paletteMenu);
paletteMenu[1].data = (void*)iconB;
paletteMenu[2].data = (void*)iconB;
MenuPopupCreate(iconB, XtNumber(paletteMenu), paletteMenu);
info->widget = iconA;
info->widget2 = iconB;
info->shownPixmap = pix;
XtAddCallback(iconA, XtNdestroyCallback, (XtCallbackProc)freePatternInfo, (XtPointer)info);
return iconA;
}
Widget AddPatternInfo(void *piArg, Pixmap pix, Pixel pxl)
{
PatternInfo *pi = (PatternInfo *)piArg;
return AddPattern(pi->widget, pi->paint, pix, pxl);
}
void ChangePattern(void *iArg, Pixmap pix)
{
PatternInfo *info = (PatternInfo *)iArg;
int depth;
Display *dpy = XtDisplay(info->paint);
Pixmap pfree1 = None, pfree2 = None;
GetPixmapWHD(dpy, pix, &info->width, &info->height, &depth);
if (info->pixmap != info->shownPixmap)
pfree1 = info->shownPixmap;
if (info->pixmap != None)
pfree2 = info->pixmap;
info->pixmap = pix;
if (info->width < PAT_MIN_WH || info->height < PAT_MIN_WH) {
int nw = (info->width < PAT_MIN_WH) ? PAT_MIN_WH : info->width;
int nh = (info->height < PAT_MIN_WH) ? PAT_MIN_WH : info->height;
int x, y;
GC gc = XtGetGC(info->paint, 0, 0);
pix = XCreatePixmap(dpy, DefaultRootWindow(dpy), nw, nh, depth);
for (y = 0; y < nh; y += info->height)
for (x = 0; x < nw; x += info->width)
XCopyArea(dpy, info->pixmap, pix, gc,
0, 0, info->width, info->height, x, y);
XtReleaseGC(info->paint, gc);
}
installPatternPixmap(info, pix);
info->shownPixmap = pix;
if (pfree1 != None)
XFreePixmap(dpy, pfree1);
if (pfree2 != None)
XFreePixmap(dpy, pfree2);
}
/*
** Save configuration
*/
static void saveConfigOkCallback(Widget il, LocalInfo *info, char *file)
{
Widget parent = XtParent(info->primaryList);
WidgetList children;
int nchildren;
int i;
FILE *fd;
Colormap cmap;
XtVaGetValues(parent, XtNchildren, &children, XtNnumChildren, &nchildren, NULL);
XtVaGetValues(GetShell(parent), XtNcolormap, &cmap, NULL);
if (nchildren == 0) {
Notice(parent, "No information to save");
return;
}
StateSetBusyWatch(True);
if ((fd = fopen(file, "w")) == NULL) {
Notice(parent, "Unable to open file '%s' for writing", file);
return;
}
fprintf(fd, "reset\n\n");
for (i = 0; i < nchildren; i++) {
PatternInfo *pi;
pi = NULL;
XtVaGetValues(children[i], XtNradioData, &pi, NULL);
if (pi == NULL)
continue;
if (pi->pixmap == None) {
XColor col;
int r,g,b;
col.pixel = pi->pixel;
col.flags = DoRed|DoGreen|DoBlue;
XQueryColor(XtDisplay(parent), cmap, &col);
r = (col.red >> 8) & 0xff;
g = (col.green >> 8) & 0xff;
b = (col.blue >> 8) & 0xff;
fprintf(fd, "solid #%02x%02x%02x\n",r,g,b);
} else {
extern void WriteAsciiPNMfd(FILE *, Image *);
Image *image;
fprintf(fd, "pattern BeginData\n");
image = PixmapToImage(info->paint, pi->pixmap, cmap);
WriteAsciiPNMfd(fd, image);
ImageDelete(image);
fprintf(fd, "\nEndData\n");
}
}
fclose(fd);
StateSetBusyWatch(False);
}
static void saveConfigCallback(Widget w, LocalInfo *info, XtPointer junk)
{
GetFileName(info->paint, 2, ".XPaintrc",
(XtCallbackProc)saveConfigOkCallback, (XtPointer)info);
}
static void loadConfigOkCallback(Widget il, LocalInfo *info, char *file)
{
RCInfo *rcInfo = ReadRC(file);
if (rcInfo == NULL) {
Notice(info->paint, "Unable to open file %s", file);
return;
}
makePaletteArea(info, rcInfo);
FreeRC(rcInfo);
}
static void loadConfigCallback(Widget w, LocalInfo *info, XtPointer junk)
{
GetFileName(info->paint, 3, ".XPaintrc",
(XtCallbackProc)loadConfigOkCallback, (XtPointer)info);
}
/*
** Pattern edit/add callback
*/
static void addSolidOk(Widget w, LocalInfo *info, XColor *col)
{
StateShellBusy(w, False);
if (col != NULL) {
Pixel pix = PaletteAlloc(info->map, col);
AddPattern(info->primaryList, info->paint, None, pix);
}
}
static void addSolidCallback(Widget w, XtPointer wlArg, XtPointer junk2)
{
LocalInfo *info = (LocalInfo *)wlArg;
Widget paint = info->paint;
Pixel bg;
StateShellBusy(paint, True);
XtVaGetValues(paint, XtNbackground, &bg, NULL);
ColorEditor(paint, bg, info->map, False,
(XtCallbackProc)addSolidOk, (XtPointer)info);
}
static void addPatternCallback(Widget w, XtPointer wlArg, XtPointer junk2)
{
void PatternEdit(Widget, Pixmap, Widget);
LocalInfo *info = (LocalInfo *)wlArg;
PatternEdit(info->paint, None, info->primaryList);
}
static void lookupPatternCallback(Widget w, XtPointer infoArg, XtPointer junk2)
{
LocalInfo *info = (LocalInfo *)infoArg;
int nchildren, i;
WidgetList children;
Widget icon, list;
Colormap cmap;
Pixel p;
PatternInfo *pi;
DoGrabPixel(w, &p, &cmap);
if (cmap != info->map->cmap) {
XColor col;
col.pixel = p;
col.flags = DoRed|DoGreen|DoBlue;
XQueryColor(XtDisplay(w), cmap, &col);
if (!PaletteLookupColor(info->map, &col, &p))
p = PaletteAlloc(info->map, &col);
}
#ifndef LOOKUP_OUTSIDE
if (XtParent(w) == info->primaryBox)
list = info->primaryList;
else
list = info->secondaryList;
#else
if (XtNameToWidget(XtParent(w), "viewport2.patternRack") == info->primaryBox)
list = info->primaryList;
else
list = info->secondaryList;
#endif
XtVaGetValues(XtParent(list),
XtNnumChildren, &nchildren,
XtNchildren, &children,
NULL);
for (i = 0; i < nchildren; i++) {
pi = NULL;
XtVaGetValues(children[i], XtNradioData, &pi, NULL);
if (pi == NULL || pi->pixmap != None)
continue;
if (pi->pixel == p) {
XawToggleSetCurrent(list, (XtPointer)pi);
return;
}
}
icon = AddPattern(info->primaryList, info->paint, None, p);
XtVaGetValues(icon, XtNradioData, &pi, NULL);
XawToggleSetCurrent(list, (XtPointer)pi);
}
/*
** Convert RC file information into the pattern box info
*/
static void makePaletteArea(LocalInfo *info, RCInfo *rcInfo)
{
Widget firstIcon, icon;
Widget pattern = info->secondaryBox;
XColor col, rgb;
int i, j;
/*
** Allocate the color entries
*/
rcInfo->colorFlags = (Boolean *)XtCalloc(sizeof(Boolean),
rcInfo->ncolors);
rcInfo->colorPixels = (Pixel *)XtCalloc(sizeof(Pixel),
rcInfo->ncolors);
for (i = 0; i < rcInfo->ncolors; i++)
rcInfo->colorFlags[i] = False;
for (i = 0; i < rcInfo->ncolors; i++) {
if (XLookupColor(XtDisplay(info->paint), info->map->cmap,
rcInfo->colors[i], &col, &rgb) ||
XParseColor(XtDisplay(info->paint), info->map->cmap,
rcInfo->colors[i], &col)) {
rcInfo->colorPixels[i] = PaletteAlloc(info->map, &col);
rcInfo->colorFlags[i] = True;
for (j = 0; j < i; j++)
if (rcInfo->colorPixels[i] == rcInfo->colorPixels[j])
rcInfo->colorFlags[i] = False;
}
}
/*
** Sneeky pass to AddPattern()
*/
hiddenLocalInfo = info;
firstIcon = pattern;
for (i = 0; i < rcInfo->ncolors; i++) {
if (!rcInfo->colorFlags[i])
continue;
icon = AddPattern(firstIcon, info->paint, None, rcInfo->colorPixels[i]);
if (firstIcon == pattern)
firstIcon = icon;
}
for (i = 0; i < rcInfo->nimages; i++) {
Pixmap pix;
rcInfo->images[i]->refCount++;
pix = None;
ImageToPixmapCmap(rcInfo->images[i], info->paint, &pix, info->map->cmap);
icon = AddPattern(firstIcon, info->paint, pix, 0);
if (firstIcon == pattern)
firstIcon = icon;
}
}
/*
** First level menu callbacks.
*/
static void closeOkCallback(Widget shell, XtPointer junk, XtPointer junk2)
{
XtDestroyWidget(shell);
}
static void closeCancelCallback(Widget shell, XtPointer junk, XtPointer junk2)
{
}
static void closeCallback(Widget w, XtPointer paintArg, XtPointer junk2)
{
Widget paint = (Widget)paintArg;
Boolean flg;
XtVaGetValues(paint, XtNdirty, &flg, NULL);
if (flg)
AlertBox(GetShell(paint), "Unsaved changes!\nDo you really wish to close?",
closeOkCallback, closeCancelCallback, NULL);
else
XtDestroyWidget(GetShell(paint));
}
/*
**
*/
static void fatCallback(Widget w, XtPointer paint, XtPointer junk2)
{
void FatbitsEdit(Widget);
FatbitsEdit((Widget)paint);
}
static void gridCallback(Widget w, XtPointer paintArg, XtPointer junk2)
{
Widget paint = (Widget)paintArg;
Boolean v;
XtVaGetValues(paint, XtNgrid, &v, NULL);
v = !v;
XtVaSetValues(paint, XtNgrid, v, NULL);
MenuCheckItem(w, v);
}
static void snapCallback(Widget w, XtPointer paintArg, XtPointer junk2)
{
Widget paint = (Widget)paintArg;
Boolean v;
XtVaGetValues(paint, XtNsnapOn, &v, NULL);
v = !v;
XtVaSetValues(paint, XtNsnapOn, v, NULL);
MenuCheckItem(w, v);
}
/*
**
*/
static int snapSpacing = 10;
static void changeSnapOkCallback(Widget paint, void *junk, XtPointer infoArg)
{
TextPromptInfo *info = (TextPromptInfo*)infoArg;
int v = atoi(info->prompts[0].rstr);
if (v < 1 || v > 100) {
Notice(paint,"Bad snap spacing.\nShould be between 2 and 100");
return;
}
snapSpacing = v;
XtVaSetValues(paint, XtNsnap, v, NULL);
}
static void changeSnapCallback(Widget w, XtPointer paintArg, XtPointer junk2)
{
Widget paint = (Widget)paintArg;
static TextPromptInfo info;
static struct textPromptInfo value[1];
static char buf[10];
sprintf(buf, "%d", snapSpacing);
value[0].prompt = "Spacing:";
value[0].str = buf;
value[0].len = 4;
info.prompts = value;
info.title = "Enter desired snap spacing";
info.nprompt = 1;
TextPrompt(paint, "linewidth", &info, changeSnapOkCallback, NULL, NULL);
}
static void sizeCallback(Widget w, XtPointer paintArg, XtPointer junk2)
{
Widget paint = (Widget)paintArg;
SizeSelect(GetShell(paint), paint, NULL);
}
/*
**
*/
static void zoomAddChild(Widget paint, int zoom)
{
Cardinal nc;
Widget t, box = XtParent(paint);
WidgetList children;
int dw, dh;
/*
** 1 child == just paint widget
** 2 children paint widget + normal size view
*/
XtVaGetValues(box, XtNchildren, &children, XtNnumChildren, &nc, NULL);
XtVaGetValues(paint, XtNdrawWidth, &dw, XtNdrawHeight, &dh, NULL);
if (nc == 1 && zoom > 1 && dw < 256 && dh < 256) {
/*
** Add child
*/
t = XtVaCreateManagedWidget("norm", paintWidgetClass, box,
XtNpaint, paint,
XtNzoom, 1,
NULL);
GraphicAdd(t);
} else if (nc != 1 && zoom <= 1) {
/*
** Remove child
*/
t = children[(children[0] == paint) ? 1 : 0];
XtDestroyWidget(t);
}
}
static void zoomOkCallback(Widget w, XtPointer paintArg, XtPointer infoArg)
{
Widget paint = (Widget)paintArg;
TextPromptInfo *info = (TextPromptInfo*)infoArg;
int zoom = atoi(info->prompts[0].rstr);
if (zoom <= 0) {
Notice(paint, "Invalid zoom");
} else {
XtVaSetValues(paint, XtNzoom, zoom, NULL);
zoomAddChild(paint, zoom);
}
}
void zoomCallback(Widget w, XtPointer paintArg, XtPointer junk2)
{
static TextPromptInfo info;
static struct textPromptInfo values[2];
char buf[80];
int zoom;
Widget paint = (Widget)paintArg;
info.nprompt = 1;
info.prompts = values;
info.title = "Change zoom factor for image";
values[0].prompt = "Zoom: ";
values[0].len = 4;
values[0].str = buf;
XtVaGetValues(paint, XtNzoom, &zoom, NULL);
sprintf(buf, "%d", (int)zoom);
TextPrompt(GetShell(paint), "zoomselect", &info, zoomOkCallback, NULL, paint);
}
/*
**
*/
static void rotateTo(Widget w, XtPointer paintArg, XtPointer junk2)
{
Widget paint = (Widget)paintArg;
float t = M_PI / 4.0;
pwMatrix m;
String lbl;
XtVaGetValues(w, XtNlabel, &lbl, NULL);
t = atof(lbl);
if (t == 0.0)
return;
t *= M_PI / 180.0;
m[0][0] = cos(t);
m[0][1] = -sin(t);
m[1][0] = sin(t);
m[1][1] = cos(t);
PwRegionAppendMatrix(paint, m);
}
static void rotateOkCallback(Widget paint, void *junk, XtPointer infoArg)
{
TextPromptInfo *info = (TextPromptInfo*)infoArg;
float t = atof(info->prompts[0].rstr) * M_PI / 180.0;
pwMatrix m;
m[0][0] = cos(t);
m[0][1] = -sin(t);
m[1][0] = sin(t);
m[1][1] = cos(t);
PwRegionAppendMatrix(paint, m);
}
static void rotate(Widget w, XtPointer paintArg, XtPointer junk2)
{
Widget paint = (Widget)paintArg;
static TextPromptInfo info;
static struct textPromptInfo value[1];
static char buf[10];
sprintf(buf, "%d", snapSpacing);
value[0].prompt = "Angle (in Degrees):";
value[0].str = buf;
value[0].len = 4;
info.prompts = value;
info.title = "Enter desired rotation";
info.nprompt = 1;
TextPrompt(paint, "linewidth", &info, rotateOkCallback, NULL, NULL);
}
static void resetMat(Widget w, XtPointer paintArg, XtPointer junk2)
{
pwMatrix m;
m[0][0] = m[1][1] = 1;
m[1][0] = m[0][1] = 0;
PwRegionReset((Widget)paintArg, True);
}
static void nudgeBox(Widget w, XtPointer paintArg, XtPointer junk2)
{
/* RegionBox((Widget)paintArg); */
}
static void prCallback(Widget paint, Widget w, Boolean flag)
{
XtVaSetValues(w, XtNsensitive, flag, NULL);
}
/*
** Background changer
*/
static void changeBgOk(Widget w, Palette *map, XColor *col)
{
StateShellBusy(w, False);
if (col != NULL) {
Pixel pix = PaletteAlloc(map, col);
XtVaSetValues(w, XtNbackground, pix, NULL);
}
}
static void changeBackground(Widget w, XtPointer paintArg, XtPointer junk2)
{
Widget paint = (Widget)paintArg;
Colormap cmap;
Pixel bg;
Palette *map;
StateShellBusy(paint, True);
XtVaGetValues(GetShell(paint), XtNcolormap, &cmap, NULL);
XtVaGetValues(paint, XtNbackground, &bg, NULL);
map = PaletteFind(paint, cmap);
ColorEditor(paint, bg, map,
False, (XtCallbackProc)changeBgOk, (XtPointer)map);
}
/*
** Start of graphic window creation routines
*/
Widget makeGraphicShell(Widget wid)
{
Arg args[20];
int nargs = 0;
Widget shell;
XtSetArg(args[nargs], XtNtitle, DEFAULT_TITLE); nargs++;
XtSetArg(args[nargs], XtNiconName, DEFAULT_TITLE); nargs++;
shell = XtAppCreateShell("Canvas", "Canvas",
topLevelShellWidgetClass, XtDisplay(GetToplevel(wid)),
args, nargs);
return shell;
}
static Widget mkPatternArea(Widget parent, Widget left, char *name, Widget *pform, LocalInfo *info)
{
Widget form, label, pattern, vport, lookup;
form = XtVaCreateManagedWidget("patternRackForm",
formWidgetClass, parent,
XtNborderWidth, 0,
XtNfromHoriz, left,
XtNleft, XtChainLeft,
XtNright, XtChainLeft,
NULL);
if (pform != NULL)
*pform = form;
label = XtVaCreateManagedWidget(name, labelWidgetClass, form,
XtNborderWidth, 0,
NULL);
#ifdef LOOKUP_OUTSIDE
lookup = XtVaCreateManagedWidget("lookup",
commandWidgetClass, form,
XtNfromHoriz, label,
NULL);
#else
lookup = label;
#endif
vport = XtVaCreateManagedWidget("viewport2",
viewportWidgetClass, form,
XtNallowVert, True,
XtNuseBottom, True,
XtNuseRight, True,
XtNfromVert, lookup,
NULL);
pattern = XtVaCreateWidget("patternRack",
boxWidgetClass, vport,
NULL);
#ifndef LOOKUP_OUTSIDE
lookup = XtVaCreateManagedWidget("lookup",
commandWidgetClass, pattern,
NULL);
#endif
XtAddCallback(lookup, XtNcallback, lookupPatternCallback, (XtPointer)info);
return pattern;
}
Widget graphicCreate(Widget shell, int width, int height, int zoom, Pixmap pix, Colormap cmap)
{
Widget form, viewport, pattern, bar;
Widget pane, pane1, pform;
Widget paint;
Widget icon, firstIcon;
Widget add, edit;
WidgetList child;
int nchild;
RCInfo *rcInfo;
Palette *map;
int i, j;
int depth;
LocalInfo *info = XtNew(LocalInfo);
PatternInfo *pData;
/*
** Menu Bar
*/
if (cmap == None) {
map = PaletteCreate(shell);
cmap = map->cmap;
} else {
map = PaletteFind(shell, cmap);
}
depth = map->depth;
XtVaSetValues(shell, XtNcolormap, cmap, NULL);
PaletteAddUser(map, shell);
info->map = map;
pane = XtVaCreateManagedWidget("pane",
panedWidgetClass, shell,
NULL);
rcInfo = ReadDefaultRC();
/*
** Menu area
*/
form = XtVaCreateManagedWidget("form1",
formWidgetClass, pane,
NULL);
bar = MenuBarCreate(form, XtNumber(menuBar), menuBar);
XtVaSetValues(form, XtNshowGrip, False, NULL);
/*
** Drawing Area
*/
viewport = XtVaCreateWidget("viewport",
viewportWidgetClass, pane,
XtNfromVert, bar,
XtNallowVert, True,
XtNallowHoriz, True,
XtNuseBottom, True,
XtNuseRight, True,
XtNtop, XtChainTop,
NULL);
/*
** Custom Drawing Widget here
** First read the file and convert to a bitmap
*/
pane1 = XtVaCreateWidget("paintBox",
boxWidgetClass, viewport,
XtNbackgroundPixmap, GetBackgroundPixmap(viewport),
NULL);
/*
** Try and do something nice for the user
*/
if (zoom == -1 && width <= 64 && height <= 64) {
int wth = width;
int hth = height;
if (pix != None)
GetPixmapWHD(XtDisplay(pane1), pix, &wth, &hth, NULL);
if (wth <= 64 && hth <= 64 && wth != 0 && hth != 0)
zoom = 6;
}
paint = XtVaCreateManagedWidget("paint",
paintWidgetClass, pane1,
XtNdrawWidth, width,
XtNdrawHeight, height,
XtNzoom, zoom,
XtNpixmap, pix,
XtNcolormap, cmap,
XtNallowResize, True,
XtNshowGrip, False,
NULL);
XtSetKeyboardFocus(pane, paint);
zoomAddChild(paint, zoom);
info->paint = paint;
OperationSetPaint(paint);
ccpAddStdPopup(paint);
XtManageChild(pane1);
XtManageChild(viewport);
XtAddCallback(fileMenu[SAVE_CONFIG].widget,
XtNcallback, (XtCallbackProc)saveConfigCallback, (XtPointer)info);
XtAddCallback(fileMenu[LOAD_CONFIG].widget,
XtNcallback, (XtCallbackProc)loadConfigCallback, (XtPointer)info);
ccpAddUndo(editMenu[UNDO_ITEM].widget, paint);
ccpAddCut(editMenu[CUT_ITEM].widget, paint);
ccpAddCopy(editMenu[COPY_ITEM].widget, paint);
ccpAddPaste(editMenu[PASTE_ITEM].widget, paint);
ccpAddClear(editMenu[CLEAR_ITEM].widget, paint);
ccpAddDuplicate(editMenu[DUP_ITEM].widget, paint);
XtAddCallback(editMenu[SELECT_ALL_ITEM].widget,
XtNcallback, StdSelectAllCallback, (XtPointer)paint);
XtAddCallback(fileMenu[SAVEAS_ITEM].widget,
XtNcallback, StdSaveAsFile, (XtPointer)paint);
XtAddCallback(fileMenu[SAVE_ITEM].widget,
XtNcallback, StdSaveFile, (XtPointer)paint);
ccpAddSaveRegion(fileMenu[SAVER_ITEM].widget, paint);
XtAddCallback(fileMenu[CLOSE_ITEM].widget,
XtNcallback, closeCallback, (XtPointer)paint);
XtAddCallback(otherMenu[GRID_ITEM].widget,
XtNcallback, gridCallback, (XtPointer)paint);
XtAddCallback(otherMenu[SNAP_ITEM].widget,
XtNcallback, snapCallback, (XtPointer)paint);
XtAddCallback(otherMenu[CHSNAP_ITEM].widget,
XtNcallback, changeSnapCallback, (XtPointer)paint);
XtAddCallback(otherMenu[FAT_ITEM].widget,
XtNcallback, fatCallback, (XtPointer)paint);
XtAddCallback(otherMenu[CHSIZE_ITEM].widget,
XtNcallback, sizeCallback, (XtPointer)paint);
XtAddCallback(otherMenu[CHZOOM_ITEM].widget,
XtNcallback, zoomCallback, (XtPointer)paint);
XtAddCallback(otherMenu[EDIT_BACKGROUND].widget,
XtNcallback, changeBackground, (XtPointer)paint);
ccpAddRegionFlipX(regionMenu[RG_FLIPX_ITEM].widget, paint);
ccpAddRegionFlipY(regionMenu[RG_FLIPY_ITEM].widget, paint);
ccpAddRegionInvert(regionMenu[RG_INVERT_ITEM].widget, paint);
ccpAddRegionSharpen(regionMenu[RG_SHARPEN_ITEM].widget, paint);
ccpAddRegionSmooth(regionMenu[RG_SMOOTH_ITEM].widget, paint);
ccpAddRegionEdge(regionMenu[RG_EDGE_ITEM].widget, paint);
ccpAddRegionEmbose(regionMenu[RG_EMBOSE_ITEM].widget, paint);
ccpAddRegionOilPaint(regionMenu[RG_OIL_ITEM].widget, paint);
for (i = 0; i < XtNumber(rotateMenu); i++) {
if (rotateMenu[i].name[0] == '\0')
continue;
XtAddCallback(rotateMenu[i].widget, XtNcallback,
(XtCallbackProc)rotateTo, (XtPointer)paint);
XtAddCallback(paint, XtNregionCallback, (XtCallbackProc)prCallback,
(XtPointer)rotateMenu[i].widget);
prCallback(paint, rotateMenu[i].widget, False);
}
XtAddCallback(regionMenu[RG_ROTATE].widget,
XtNcallback, (XtCallbackProc)rotate, (XtPointer)paint);
XtAddCallback(paint, XtNregionCallback, (XtCallbackProc)prCallback,
(XtPointer)regionMenu[RG_ROTATE].widget);
prCallback(paint, regionMenu[RG_ROTATE].widget, False);
XtAddCallback(regionMenu[RG_RESET].widget,
XtNcallback, (XtCallbackProc)resetMat, (XtPointer)paint);
#ifdef RG_BOX
XtAddCallback(regionMenu[RG_BOX].widget,
XtNcallback, (XtCallbackProc)nudgeBox, (XtPointer)paint);
#endif
XtAddCallback(paint, XtNregionCallback, (XtCallbackProc)prCallback,
(XtPointer)regionMenu[RG_RESET].widget);
prCallback(paint, regionMenu[RG_RESET].widget, False);
form = XtVaCreateManagedWidget("form2",
formWidgetClass, pane,
XtNskipAdjust, True,
NULL);
pattern = mkPatternArea(form, None, "primary", &pform, info);
info->primaryBox = pattern;
pattern = mkPatternArea(form, pform, "secondary", &pform, info);
info->secondaryBox = pattern;
info->primaryList = None;
info->secondaryList = None;
/*
** Now construct the paletter area and set the
** primary and secondary selections correctly
*/
makePaletteArea(info, rcInfo);
XtVaGetValues(info->primaryBox, XtNchildren, &child,
XtNnumChildren, &nchild,
NULL);
XtVaGetValues(child[0], XtNradioData, &pData, NULL);
XawToggleSetCurrent(info->primaryList, (XtPointer)pData);
XtVaGetValues(info->secondaryBox, XtNchildren, &child,
XtNnumChildren, &nchild,
NULL);
if (nchild == 1)
XtVaGetValues(child[0], XtNradioData, &pData, NULL);
else
XtVaGetValues(child[1], XtNradioData, &pData, NULL);
XawToggleSetCurrent(info->secondaryList, (XtPointer)pData);
XtManageChild(info->primaryBox);
XtManageChild(info->secondaryBox);
/*
** A few buttons for help...
*/
add = XtVaCreateManagedWidget("addPattern",
commandWidgetClass, form,
XtNfromHoriz, pform,
XtNfromVert, None,
XtNleft, XtChainRight,
XtNright, XtChainRight,
XtNtop, XtChainTop,
XtNbottom, XtChainTop,
NULL);
/*
** If we are on a small static colormap, we shouldn't be able to do an add. XXX
*/
edit = XtVaCreateManagedWidget("addSolid",
commandWidgetClass, form,
XtNfromHoriz, pform,
XtNfromVert, add,
XtNleft, XtChainRight,
XtNright, XtChainRight,
XtNtop, XtChainTop,
XtNbottom, XtChainTop,
NULL);
if (edit != None)
XtAddCallback(edit, XtNcallback, addSolidCallback, (XtPointer)info);
XtAddCallback(add , XtNcallback, addPatternCallback, (XtPointer)info);
XtAddCallback(paint, XtNdestroyCallback, destroyCallback, (XtPointer)info);
AddDestroyCallback(shell,
(void (*)(Widget, void *, XEvent *))closeCallback,(void*)paint);
SetIconImage(shell, False);
XtRealizeWidget(shell);
GraphicAdd(paint);
return shell;
}
typedef struct cwi_s {
Widget paint;
void *id;
struct cwi_s *next;
} CanvasWriteInfo;
static CanvasWriteInfo *cwiHead = NULL;
void removeCWI(Widget w, CanvasWriteInfo *ci, XtPointer junk)
{
CanvasWriteInfo *cur = cwiHead, **pp = &cwiHead;
while (cur != NULL && cur != ci) {
pp = &cur->next;
cur = cur->next;
}
if (cur == NULL)
return;
*pp = cur->next;
XtFree((XtPointer)ci);
}
void *GraphicGetReaderId(Widget paint)
{
CanvasWriteInfo *cur;
paint = GetShell(paint);
for (cur = cwiHead; cur != NULL && cur->paint != paint; cur = cur->next)
;
if (cur == NULL)
return NULL;
return cur->id;
}
void GraphicOpenFile(Widget w, XtPointer fileArg, XtPointer imageArg)
{
char *file = (char *)fileArg;
Image *image = (Image *)imageArg;
Colormap cmap;
Pixmap pix;
Widget shell = makeGraphicShell(w);
CanvasWriteInfo *ci = XtNew(CanvasWriteInfo);
ci->next = cwiHead;
cwiHead = ci;
ci->paint = shell;
ci->id = GetFileNameGetLastId();
XtAddCallback(shell, XtNdestroyCallback, (XtCallbackProc)removeCWI, (XtPointer)ci);
if (ImageToPixmap(image, shell, &pix, &cmap)) {
/*
** If mask != None, set the mask region color to the BG color of the Canvas
*/
if ((shell = graphicCreate(shell, 0, 0, -1, pix, cmap)) != None) {
char *cp = strrchr(file, '/');
if (cp == NULL)
cp = file;
else
cp++;
XtVaSetValues(shell, XtNiconName, cp, XtNtitle, file, NULL);
} else {
XtDestroyWidget(shell);
}
} else {
Notice(w, "Unable to create paint window with image");
XtDestroyWidget(shell);
}
}
static void doCreate(Widget wid, int width, int height, int zoom)
{
graphicCreate(makeGraphicShell(wid), width, height, zoom, None, None);
}
void GraphicCreate(Widget wid, int value)
{
int width, height;
switch (value) {
case 0:
GetDefaultWH(&width, &height);
graphicCreate(makeGraphicShell(wid), width, height, -1, None, None);
break;
case 1:
GetFileName(GetToplevel(wid), 0, NULL, GraphicOpenFile, NULL);
break;
case 2:
SizeSelect(wid, None, doCreate);
break;
}
}